﻿using System;
using System.Windows.Forms;
using CHIP8Emulator;

namespace CHIP8 {
    public partial class Form1 : Form {
        private readonly Logger _logger;
        private CHIP8EmulatorControl _emulator;

        public Form1(Logger logger) {
            InitializeComponent();
            _logger = new CompositeLogger().Add(_logControl.CreateLogger()).Add(logger);
            LogStart();

            CreateEmulatorControl();
            _emulator.InitBy(_logger);
            _disassemblyCodeControl.InitBy(_logger);
            UpdateToolBox(_emulator.State);
        }

        private void CreateEmulatorControl() {
            _emulator = new CHIP8EmulatorControl();
            _emulator.Dock = DockStyle.Fill;
            _emulator.Name = "_emulator";
            _emulator.KeyDown += OnKeyDown;
            _emulator.KeyUp += OnKeyUp;
            _emulator.Click += (sender, e) => _emulator.Focus();
            _emulator.OnStateChanged += (sender, e) => UpdateToolBox(e.State);

            SuspendLayout();
            splitContainer2.Panel1.Controls.Add(_emulator);
            ResumeLayout(true);
        }

        private void LogStart() {
            _logger.Log(LogMessageType.Info, "Emulator started");
        }

        private void quitToolStripMenuItem_Click(object sender, EventArgs e) {
            Close();
        }

        private void LogQuit(CloseReason reason) {
            _logger.Log(LogMessageType.Info, "Emulator quit (Reason '{0}')", reason);
        }

        private void aboutToolStripMenuItem_Click(object sender, EventArgs e) {
            MessageBox.Show(this, "About", "About", MessageBoxButtons.OK, MessageBoxIcon.None);
        }

        private void openToolStripMenuItem_Click(object sender, EventArgs e) {
            OpenFileDialog openFileDialog = new OpenFileDialog();
            if (openFileDialog.ShowDialog() == DialogResult.OK) {
                _logger.Log(LogMessageType.Info, "Opening program {0}", openFileDialog.FileName);
                _emulator.LoadFrom(openFileDialog.FileName);
            }
            UpdateToolBox(_emulator.State);
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e) {
            LogQuit(e.CloseReason);
        }

        private void OnKeyDown(object sender, KeyEventArgs e) {
            _emulator.PressKey(e.KeyCode);
        }

        private void OnKeyUp(object sender, KeyEventArgs e) {
            _emulator.ReleaseKey(e.KeyCode);
        }

        private void _btnRun_Click(object sender, EventArgs e) {
            _emulator.Run();
            UpdateToolBox(_emulator.State);
        }

        private void _btnPause_Click(object sender, EventArgs e) {
            _emulator.Pause();
            UpdateToolBox(_emulator.State);
        }

        private void _btnStop_Click(object sender, EventArgs e) {
            _emulator.Stop();
            UpdateToolBox(_emulator.State);
        }

        private void UpdateToolBox(State state) {
            switch (state) {
            case State.Empty:
                _btnRun.Enabled = _btnPause.Enabled = _btnStop.Enabled = false;
                break;
            case State.Loaded:
                _btnRun.Enabled = true;
                _btnPause.Enabled = _btnStop.Enabled = false;
                break;
            case State.Started:
                _btnRun.Enabled = false;
                _btnPause.Enabled = _btnStop.Enabled = true;
                break;
            case State.Paused:
                _btnPause.Enabled = false;
                _btnRun.Enabled = _btnStop.Enabled = true;
                break;
            default:
                throw new ArgumentOutOfRangeException("state");
            }
        }
    }
}